package data

import (
	"fmt"
	"sync"
	"yunj/pkg/global"
	"yunj/pkg/yunj/app/enum/stateenum"
	"yunj/pkg/yunj/app/model"
	"yunj/pkg/yunj/core/db"
)

var dataDepartmentMutex sync.RWMutex

type department struct {
	normalDepartments     []*model.AdminDepartment          // 正常部门
	normalDepartmentMap   map[uint64]*model.AdminDepartment // id:department
	normalDepartmentIds   []uint64                          // 按sort排序
	normalDepartmentIdIdx map[uint64]int                    // id:index
}

var Department = &department{}

// 获取正常部门
func (s *department) GetNormalDepartments() []*model.AdminDepartment {
	dataDepartmentMutex.RLock()         // 获取读锁
	defer dataDepartmentMutex.RUnlock() // 释放读锁
	return s.normalDepartments
}

// 获取正常部门map
func (s *department) GetNormalDepartmentMap() map[uint64]*model.AdminDepartment {
	dataDepartmentMutex.RLock()         // 获取读锁
	defer dataDepartmentMutex.RUnlock() // 释放读锁
	return s.normalDepartmentMap
}

// 是否有正常的数据
func (s *department) HasNormalData() bool {
	dataDepartmentMutex.RLock()         // 获取读锁
	defer dataDepartmentMutex.RUnlock() // 释放读锁
	return len(s.normalDepartments) > 0
}

// 根据id获取部门
func (s *department) GetDepartmentById(id uint64) (department *model.AdminDepartment) {
	dataDepartmentMutex.RLock()         // 获取读锁
	defer dataDepartmentMutex.RUnlock() // 释放读锁
	if _department, exists := s.normalDepartmentMap[id]; exists && _department != nil {
		department = _department
	}
	return
}

// 准备部门数据
func (s *department) prepareDepartments() (err error) {
	var departments []*model.AdminDepartment
	if err = global.MySQL.Where("state = ?", stateenum.NORMAL).Order("sort asc").Find(&departments).Error; err != nil {
		err = fmt.Errorf("状态正常部门数据获取异常！%v", err)
		return
	}

	departmentMap := map[uint64]*model.AdminDepartment{}
	departmentIds := make([]uint64, 0, len(departments))
	departmentIdIdx := map[uint64]int{}
	for idx, department := range departments {
		departmentMap[department.Id] = department
		departmentIds = append(departmentIds, department.Id)
		departmentIdIdx[department.Id] = idx
		department.InitSubDepartments(departments)
	}
	// 附加子部门
	s.normalDepartments = departments
	s.normalDepartmentMap = departmentMap
	s.normalDepartmentIds = departmentIds
	s.normalDepartmentIdIdx = departmentIdIdx
	return
}

// 处理所有部门数据的完整属性值（补充完整名称等），并清理缓存
func HandleAllDepartmentFullAttr() (err error) {
	var items []*model.AdminDepartment
	if err = global.MySQL.Where("state <> ?", stateenum.DELETED).Find(&items).Error; err != nil {
		err = fmt.Errorf("处理所有部门数据的完整属性值：数据获取异常！%v", err)
		return
	}
	if len(items) > 0 {
		// 获取所有要修改数据
		handleDepartmentFullAttr(items, map[uint64]*model.AdminDepartment{0: nil})
		dbItems := make([]map[string]interface{}, 0, len(items))
		for _, item := range items {
			dbPids, dbValueErr := item.Pids.Value()
			if dbValueErr != nil {
				err = fmt.Errorf("处理所有部门数据的完整属性值：获取pids异常！%v", dbValueErr)
				return
			}
			dbItems = append(dbItems, map[string]interface{}{
				"id":        item.Id,
				"pids":      dbPids,
				"full_name": item.FullName,
			})
		}
		// 批量修改数据
		res := db.Model(&model.AdminDepartment{}).BatchChange(dbItems)
		if res.Error != nil {
			err = fmt.Errorf("处理所有部门数据的完整属性值：批量修改数据失败！%v", res.Error)
			return
		}
	}
	// 清理缓存
	err = DepartmentPrepareOrReset()
	if err != nil {
		err = fmt.Errorf("处理所有部门数据的完整属性值：清理缓存失败！%v", err)
	}
	return
}

func handleDepartmentFullAttr(items []*model.AdminDepartment, parentsMap map[uint64]*model.AdminDepartment) (err error) {
	newParentsMap := map[uint64]*model.AdminDepartment{}
	for _, item := range items {
		parent, exists := parentsMap[item.Pid]
		if !exists {
			continue
		}
		pids := model.Uint64SliceJson{}
		parentFullName := ""
		if parent != nil {
			pids = append(parent.Pids, parent.Id)
			parentFullName = parent.FullName
		}
		fullName := ""
		if parentFullName != "" {
			fullName = parentFullName + "/"
		}
		item.Pids = pids
		item.FullName = fullName + item.Name
		newParentsMap[item.Id] = item
	}
	if len(newParentsMap) > 0 {
		return handleDepartmentFullAttr(items, newParentsMap)
	}
	return
}

// 数据准备或重置（等于缓存重置）
func DepartmentPrepareOrReset() (err error) {
	dataDepartmentMutex.Lock()         // 获取写锁
	defer dataDepartmentMutex.Unlock() // 释放写锁
	// 准备部门数据
	if err := Department.prepareDepartments(); err != nil {
		return err
	}
	return
}

// 初始化部门数据库
func InitDepartmentDbData() (err error) {
	departmentDb := db.Model(&model.AdminDepartment{})
	tableName := departmentDb.GetTableName()
	// 创建数据表
	tableSql := "CREATE TABLE IF NOT EXISTS `" + tableName + "` (" +
		"`id` int unsigned NOT NULL AUTO_INCREMENT," +
		"`pid` int unsigned NOT NULL DEFAULT '0' COMMENT '父级id'," +
		"`pids` json DEFAULT NULL COMMENT '所有的父级id'," +
		"`type` tinyint unsigned NOT NULL DEFAULT '0' COMMENT '类型。11 公司、22 子公司、33 部门、44 小组'," +
		"`name` varchar(128) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NOT NULL COMMENT '名称'," +
		"`full_name` varchar(500) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NOT NULL DEFAULT '' COMMENT '完整名称，父级名称拼接'," +
		"`code` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci DEFAULT NULL COMMENT '标识'," +
		"`intro` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NOT NULL DEFAULT '' COMMENT '简介'," +
		"`sort` int unsigned NOT NULL DEFAULT '0' COMMENT '排序'," +
		"`created_at` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP," +
		"`updated_at` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP," +
		"`state` tinyint unsigned NOT NULL DEFAULT '11' COMMENT '11 正常 | 22 回收站 | 33 已删除'," +
		"PRIMARY KEY (`id`) USING BTREE," +
		"UNIQUE KEY `uk_code` (`code`) USING BTREE" +
		") ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci ROW_FORMAT=DYNAMIC COMMENT='部门表';"
	err = global.MySQL.Exec(tableSql).Error
	if err != nil {
		err = fmt.Errorf("创建数据表%s失败！%v", tableName, err)
	}
	return
}

// 初始化部门岗位数据库
func InitDepartmentPostionDbData() (err error) {
	departmentPostionDb := db.Model(&model.AdminDepartmentPostion{})
	tableName := departmentPostionDb.GetTableName()
	// 创建数据表
	tableSql := "CREATE TABLE IF NOT EXISTS `" + tableName + "` (" +
		"`id` int unsigned NOT NULL AUTO_INCREMENT," +
		"`department_id` int unsigned NOT NULL," +
		"`postion_id` int unsigned NOT NULL," +
		"`type` tinyint unsigned NOT NULL DEFAULT '0' COMMENT '类型。11 主要负责人、22 次要负责人、0 通用'," +
		"`created_at` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP," +
		"`updated_at` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP," +
		"`deleted_at` datetime DEFAULT NULL ON UPDATE CURRENT_TIMESTAMP COMMENT '删除时间'," +
		"`state` tinyint unsigned NOT NULL DEFAULT '11' COMMENT '11 正常 | 22 回收站 | 33 已删除'," +
		"PRIMARY KEY (`id`) USING BTREE," +
		"UNIQUE KEY `uk` (`department_id`,`postion_id`,`deleted_at`) USING BTREE" +
		") ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci ROW_FORMAT=DYNAMIC COMMENT='部门岗位关系表';"
	err = global.MySQL.Exec(tableSql).Error
	if err != nil {
		err = fmt.Errorf("创建数据表%s失败！%v", tableName, err)
	}
	return
}
